////////////////////////////////////////////////////////////////////////////////
//
//	Original file Name: LevelRenderer.java
//	Originating Author: JWhitefield
//	
//	Description: Renders a level within the game world
//
////////////////////////////////////////////////////////////////////////////////

package com.jjw.game.screen;

import java.util.List;

import com.jjw.game.ITickable;
import com.jjw.game.input.InputDevice;
import com.jjw.game.world.entity.character.Entity;
import com.jjw.game.world.entity.character.Player;
import com.jjw.game.world.level.Level;
import com.jjw.game.world.level.LevelManager;
import com.jjw.game.world.tile.Tile;

/**
 * Renders a level within the game world
 * 
 * @author Jon Whitefield
 *
 */
public class LevelRenderer implements ITickable {
	
	//--------------------------------------------------------------------------
	//
	//Properties
	//
	//--------------------------------------------------------------------------
	
	//----------------------------------
	// Public
	//----------------------------------
	
	//----------------------------------
	//  Getters / Setters
	//----------------------------------
	
	//----------------------------------
	// Private
	//----------------------------------
	
	/**
	 * Screen for the level renderer
	 */
	private Screen screen;
	
	/**
	 * The current level that we are rendering  
	 */
	private Level currentLevel;
		
	/**
	 * The x offset for the level renderer
	 */
	private int offsetX = 0;
	
	/**
	 * The y offset for the level renderer
	 */
	private int offsetY = 0;

	private Player player; 
	
	//--------------------------------------------------------------------------
	//
	//  Methods
	//
	//--------------------------------------------------------------------------
	
	//----------------------------------
	// Public
	//----------------------------------
	
	public LevelRenderer( Screen screen, String startLevelReference, InputDevice inputDevice ) {

		//Set the start level to the current level
		this.currentLevel = LevelManager.getInstance().getLevelByReference(startLevelReference);
		
		//Create a screen for the level render
		this.screen = screen;
		
		this.player = new Player(inputDevice);
		
		//If the current level is not null add the player to it
		if( this.currentLevel != null )
			this.currentLevel.registerEntity(player);
	}
	
	/**
	 * Render the level 
	 */
	public void render() {
		
		//If the screen is null we can't render the level 
		if( this.screen == null )
			return;
		
		//Sets the screen offset
		this.setOffset();
		
		//Set the offset of the screen
		this.screen.setOffset(this.offsetX, this.offsetY);
		
		//Render the background first
		this.renderLevelBackground();
		
		//Render the entity's 
		this.renderEntitys();
	}
	

		
	//----------------------------------
	// Private
	//----------------------------------
	
	/**
	 * Renders the background map for the level 
	 */
	private void renderLevelBackground() {
				
		//If we don't have a current level we can't render it
		if( this.currentLevel == null )
			return;
		
		//Get the map we are rendering
		Tile backgroundMap[][] = this.currentLevel.getMap();
				
		//If we don't have a map we can't renderer it
		if( backgroundMap == null )
			return;
		
		//Place holder tile to render
		Tile tileToRender = null;
		
		//Loop through the map rendering the tiles
		for( int i = 0; i < backgroundMap.length; i++ ){
			for( int k = 0; k < backgroundMap[i].length; k++ ){
				
				//Get the tile we are going to render
				tileToRender = backgroundMap[i][k];
				
				int x = k * Tile.DEFAULT_TILE_SIZE;
				int y = i * Tile.DEFAULT_TILE_SIZE;
				
				//If this tile is null continue
				if( tileToRender == null )
					continue;
											
				//Render the tile
				tileToRender.render(this.screen, x , y);
			}
		}
	}
	
	/**
	 * Renders the levels entity's
	 */
	private void renderEntitys() {
		
		//If we don't have a current level we can't render it's entity list
		if( this.currentLevel == null )
			return;
		
		//Get the entity list 
		List<Entity> entities = this.currentLevel.getLevelEntityList();
		
		//If the list is null stop here
		if( entities == null )
			return;
		
		//Loop through each entity drawing it to the screen 
		for( Entity entity : entities ) {
			
			//Render the entity
			entity.render(this.screen);
		}
	}
	
	/**
	 * Set the offset of the screen based on the players position 
	 */
	private void setOffset(){
		
		//If the level is null then we cant set the offset
		if( this.currentLevel == null )
			return;
		
		//Try to set the offset to the middle of the screen 
		this.offsetX  = this.player.getX() - this.screen.getWidth() / 2;
		this.offsetY = this.player.getY() - this.screen.getHeight() / 2;

		//Check that it dosn't scroll off the level 
		if( this.offsetX < 0 )
			this.offsetX = 0;
		
		//Check that it dosn't scroll off the level 
		if( this.offsetY < 0 )
			this.offsetY = 0;
		
		//Check it dosn't scroll off the right edge of the level 
		if( this.offsetX + this.screen.getWidth() > this.currentLevel.levelWidth()  )
			this.offsetX = this.currentLevel.levelWidth() - this.screen.getWidth();
		
		//Check its dosn't scroll off the bottom edge of the level 
		if( this.offsetY + this.screen.getHeight() > this.currentLevel.levelHeight()  )
			this.offsetY = this.currentLevel.levelHeight() - this.screen.getHeight();
	}
	
	
	//----------------------------------
	// Overridden / Implemented
	//----------------------------------
	
	@Override
	public void tick() {
				
		//Tick the player 
		this.player.tick();
	}
}
